package com.quanyan.place.service.impl;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.quanyan.common.Plugin.Page;
import com.quanyan.common.utils.DateTimeUtils;
import com.quanyan.common.utils.DateUtils;
import com.quanyan.place.cache.PlaceRedisTemplate;
import com.quanyan.place.constants.PlaceConstants;
import com.quanyan.place.entity.*;
import com.quanyan.place.entity.apireq.ReqPlaceOrderListVo;
import com.quanyan.place.entity.vo.UnitSalePlan;
import com.quanyan.place.mapper.*;
import com.quanyan.place.service.PlaceOrderService;
import com.quanyan.place.service.PlaceTaskService;
import com.quanyan.place.wrapper.PlaceOrderServiceWrapper;
import com.quanyan.place.wrapper.PlaceWrapper;
import com.quanyan.redisCluster.utils.RedisConstants;
import com.quanyan.redisCluster.utils.RedisKey;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.Date;


/**
 * Created by Kingson.chan on 2016/6/12 0012.
 */
@Service
public class PlaceTaskServiceImpl implements PlaceTaskService {
    private static final Logger logger = LoggerFactory.getLogger(PlaceTaskServiceImpl.class);

    @Autowired
    TbBizPlaceOrderMapper tbBizPlaceOrderMapper;

    @Autowired
    TbBizPlaceOrderItemMapper tbBizPlaceOrderItemMapper;

    @Autowired
    TbBizPlaceUnitSalePlanMapper tbBizPlaceUnitSalePlanMapper;

    @Autowired
    PlaceUnitSalePlanMapper placeUnitSalePlanMapper;

    @Autowired
    TbBizPlaceOrderManagerMapper tbBizPlaceOrderManagerMapper;

    @Autowired
    TbBizPlacePayItemMapper tbBizPlacePayItemMapper;

    @Autowired
    PlaceRedisTemplate placeRedisTemplate;

    @Autowired
    PlaceOrderServiceWrapper placeOrderServiceWrapper;
    
    @Autowired
    TbBizPlaceMapper tbBizPlaceMapper;
    
    @Autowired
    PlaceWrapper placeWrapper;

    @Autowired
    PlaceOrderService placeOrderService;

    /**
     * 定期查询过期的未付款订单，释放库存
     */
    @Transactional
    @Override
    public void expiredOrderCheckTask(){
        //TODO 先从redis缓存中进行查询，查询不到再查询数据库
        if(!expiredOrderCacheCheck()){//redis访问异常，再访问数据库
            //查询过期订单
            TbBizPlaceOrderExample tbBizPlaceOrderExample = new TbBizPlaceOrderExample();
            TbBizPlaceOrderExample.Criteria tbBizPlaceOrderCriteria = tbBizPlaceOrderExample.createCriteria();
            Long expiredTime = System.currentTimeMillis() - PlaceConstants.ORDER_EXPIRED_TIME; //扫描十分钟前的未支付订单
            tbBizPlaceOrderCriteria.andOrderTimeLessThan(DateUtils.transferLongToDate(expiredTime));
            tbBizPlaceOrderCriteria.andOrderStatusEqualTo(PlaceConstants.ORDER_PREPAY_STATUS);
            tbBizPlaceOrderExample.setPage(new Page(0,100));//查询数据的大小

            List<String> placeOrderValues = new ArrayList<>();
            List<TbBizPlaceOrder> placeOrderList = tbBizPlaceOrderMapper.selectByExample(tbBizPlaceOrderExample);

            if(CollectionUtils.isNotEmpty(placeOrderList)){

                for (TbBizPlaceOrder tbBizPlaceOrder : placeOrderList) {
                    placeOrderValues.add(tbBizPlaceOrder.getPlaceOrderId());
                    logger.warn(tbBizPlaceOrder.getPlaceOrderId() + "正在设置为过期订单!");
                }

                //将过期订单设置为关闭状态
                TbBizPlaceOrderExample tbBizPlaceOrderExample1 = new TbBizPlaceOrderExample();
                TbBizPlaceOrderExample.Criteria tbBizPlaceOrderCriteria1 = tbBizPlaceOrderExample1.createCriteria();
                tbBizPlaceOrderCriteria1.andPlaceOrderIdIn(placeOrderValues);
                TbBizPlaceOrder tbBizPlaceOrder = new TbBizPlaceOrder();
                tbBizPlaceOrder.setOrderStatus(PlaceConstants.ORDER_CLOSE_STATUS);
                tbBizPlaceOrder.setOrderStatusChangeDate(new Date());
                tbBizPlaceOrderMapper.updateByExampleSelective(tbBizPlaceOrder, tbBizPlaceOrderExample1);

                //更改订单支付明细的状态为退款状态
                TbBizPlacePayItem tbBizPlacePayItem = new TbBizPlacePayItem();
                tbBizPlacePayItem.setAmountType(PlaceConstants.CREDIT_TYPE);
                TbBizPlacePayItemExample tbBizPlacePayItemExample = new TbBizPlacePayItemExample();
                TbBizPlacePayItemExample.Criteria tbBizPlacePayItemCriteria = tbBizPlacePayItemExample.createCriteria();
                tbBizPlacePayItemCriteria.andPlaceOrderIdIn(placeOrderValues);
                tbBizPlacePayItemMapper.updateByExampleSelective(tbBizPlacePayItem,tbBizPlacePayItemExample);

                //释放销售计划库存
                TbBizPlaceOrderItemExample tbBizPlaceOrderItemExample = new TbBizPlaceOrderItemExample();
                TbBizPlaceOrderItemExample.Criteria tbBizPlaceOrderItemCriteria = tbBizPlaceOrderItemExample.createCriteria();
                tbBizPlaceOrderItemCriteria.andPlaceOrderIdIn(placeOrderValues);
                List<TbBizPlaceOrderItem> tbBizPlaceOrderItems = tbBizPlaceOrderItemMapper.selectByExample(tbBizPlaceOrderItemExample);

                if(CollectionUtils.isNotEmpty(tbBizPlaceOrderItems)){
                    ReqPlaceOrderListVo reqPlaceOrderListVo = new ReqPlaceOrderListVo();
                    reqPlaceOrderListVo.setStatus(PlaceConstants.PLACE_PREORDER_STATUS);
                    reqPlaceOrderListVo.setUid(null);//清理uid
                    reqPlaceOrderListVo.setLockTime(null);//清理锁表时间
                    List<Integer> unitSalePlanIdList = new ArrayList<>();
                    reqPlaceOrderListVo.setSalePlanPrimaryKeyList(unitSalePlanIdList);

                    for (TbBizPlaceOrderItem tbBizPlaceOrderItem : tbBizPlaceOrderItems) {
                        unitSalePlanIdList.add(tbBizPlaceOrderItem.getUnitSalePlanId());
                        logger.warn(tbBizPlaceOrderItem.getUnitSalePlanId() + "正在释放库存！");
                    }
                    placeOrderService.updateSalePlanByPrimaryKeyList(reqPlaceOrderListVo);
                }
            }
        }
    }

    public boolean expiredOrderCacheCheck(){
        //TODO 缓存处理
        /*try {
            //先获取队列最新一条数据，如果过期，说明队列全部数据都过期，则进行相关处理
            OrderDetailCacheVo orderDetailCacheVo = (OrderDetailCacheVo) placeRedisTemplate.lpop(PlaceOrderServiceWrapperImpl.getOrderCacheQueueName());
            if(orderDetailCacheVo == null){
                return false;
            }


            return true;
        }
        catch (Exception e){
            e.printStackTrace();
        }*/
        return false;
    }

    /**
     * 定期检查超过锁表时间的销售计划，释放销售计划库存
     */
    @Override
    public void expiredSalePlanCheckTask() {
        // 释放销售计划库存
        Long expiredTime = System.currentTimeMillis() - PlaceConstants.ORDER_EXPIRED_TIME; //扫描十分钟前的未支付订单
        Map<String,Object> map = new HashMap<>();
        map.put("expiredTime", DateUtils.transferLongToDate(expiredTime));
        map.put("size", PlaceConstants.ORDER_EXPIRED_SIZE);
        map.put("isLockQuery", false);//TODO 是否需要加锁
        List<TbBizPlaceUnitSalePlan> selectSaleIdList = placeUnitSalePlanMapper.selectSaleIdList(map);
        if(CollectionUtils.isNotEmpty(selectSaleIdList)){
            ReqPlaceOrderListVo reqPlaceOrderListVo = new ReqPlaceOrderListVo();
            reqPlaceOrderListVo.setStatus(PlaceConstants.PLACE_PREORDER_STATUS);
            reqPlaceOrderListVo.setUid(null);//清理uid
            reqPlaceOrderListVo.setLockTime(null);//清理锁表时间
            List<UnitSalePlan> unitSalePlanIdList = new ArrayList<>();
            for (TbBizPlaceUnitSalePlan tbBizPlaceUnitSalePlan : selectSaleIdList) {
                UnitSalePlan unitSalePlan = new UnitSalePlan();
                unitSalePlan.setSaleId(tbBizPlaceUnitSalePlan.getSaleId());
                unitSalePlanIdList.add(unitSalePlan);
                logger.warn(tbBizPlaceUnitSalePlan.getSaleId() + "正在释放库存！");
            }
            reqPlaceOrderListVo.setUnitSalePlanIdList(unitSalePlanIdList);
            placeOrderService.updateSalePlanByPrimaryKeyList(reqPlaceOrderListVo);
        }
    }

    /**
     * 将已超过订单内所定场次最后时间的已经支付的订单状态设置为已经完成状态
     */
    @Override
    public void orderCompleteStatusCheckTask() {
        //查询当天订单记录中支付完成的订单，并查询当前时间大于订单详情表中预定场次的结束时间的订单
        Map<String,Object> queryMap = new HashMap<>();
        Date currentDate = new Date();
        queryMap.put("date",DateUtils.transferDateToString(currentDate));
        queryMap.put("time", DateTimeUtils.timeToStr(currentDate));

        List<PlaceOrderSalePlan> placePayOrderList = tbBizPlaceOrderManagerMapper.selectPayStatusOrderId(queryMap);
        List<PlaceOrderSalePlan> placeTicketPayOrderList = tbBizPlaceOrderManagerMapper.selectTicketOrderStatus(queryMap);
        //包场订单
        List<PlaceOrderSalePlan> placeBookAllOrderList = tbBizPlaceOrderManagerMapper.queryBookAllOrderStatus(queryMap);
        //购物车订单
        List<PlaceOrderSalePlan> placeShoppingCartOrderList = tbBizPlaceOrderManagerMapper.queryShoppingCartOrderStatus(queryMap);

        //将订单状态设置为完成状态
        if(CollectionUtils.isNotEmpty(placePayOrderList) || CollectionUtils.isNotEmpty(placeTicketPayOrderList)){
            List<String> placeOrderValues = new ArrayList<>();
            for (PlaceOrderSalePlan placePayOrder : placePayOrderList) {
                if (checkOrderFinishTime(currentDate, placePayOrder)){
                    placeOrderValues.add(placePayOrder.getPlaceOrderId());
                }
                logger.warn(placePayOrder.getPlaceOrderId() + "订单状态正在设置为已经完成状态！");
            }

            for (PlaceOrderSalePlan placeOrderSalePlan : placeTicketPayOrderList) {
                if (checkOrderFinishTime(currentDate, placeOrderSalePlan)){
                    placeOrderValues.add(placeOrderSalePlan.getPlaceOrderId());
                }
                logger.warn(placeOrderSalePlan.getPlaceOrderId() + "门票订单状态正在设置为已经完成状态！");
            }

            for (PlaceOrderSalePlan placeOrderSalePlan : placeBookAllOrderList) {
                if (checkOrderFinishTime(currentDate, placeOrderSalePlan)){
                    placeOrderValues.add(placeOrderSalePlan.getPlaceOrderId());
                }
                logger.warn(placeOrderSalePlan.getPlaceOrderId() + "包场订单状态正在设置为已经完成状态！");
            }

            for (PlaceOrderSalePlan placeShoppingCartOrder : placeShoppingCartOrderList) {
                if (checkOrderFinishTime(currentDate, placeShoppingCartOrder)){
                    placeOrderValues.add(placeShoppingCartOrder.getPlaceOrderId());
                }
                logger.warn(placeShoppingCartOrder.getPlaceOrderId() + "购物车订单状态正在设置为已经完成状态！");
            }

            TbBizPlaceOrderExample tbBizPlaceOrderExample = new TbBizPlaceOrderExample();
            TbBizPlaceOrderExample.Criteria tbBizPlaceOrderCriteria = tbBizPlaceOrderExample.createCriteria();
            tbBizPlaceOrderCriteria.andPlaceOrderIdIn(placeOrderValues);
            if (placeOrderValues.size() == 0){
                return;
            }
            tbBizPlaceOrderCriteria.andOrderStatusEqualTo(PlaceConstants.ORDER_PAYED_STATUS);
            TbBizPlaceOrder tbBizPlaceOrder = new TbBizPlaceOrder();
            tbBizPlaceOrder.setOrderStatus(PlaceConstants.ORDER_COMPLETE_PAY_STATUS);
            tbBizPlaceOrder.setEndTime(new Date());
            tbBizPlaceOrderMapper.updateByExampleSelective(tbBizPlaceOrder, tbBizPlaceOrderExample);
        }
    }

    /**
     * 检查订单是否到了完成时间
     * @param currentDate
     * @param placePayOrder
     * @return
     */
    private boolean checkOrderFinishTime(Date currentDate, PlaceOrderSalePlan placePayOrder) {
        if (StringUtils.isEmpty(placePayOrder.getDate())){
            return false;
        }
        if (StringUtils.isEmpty(placePayOrder.getEndTime())){
            return false;
        }
        String strDateTime = placePayOrder.getDate() + " " + placePayOrder.getEndTime();
        Date orderFinishTime = DateUtils.strToDate(strDateTime,DateUtils.DATE_FORMAT_YYYY_MM_DD_HH_MM_SS);
        if (orderFinishTime == null){
            return false;
        }
        if (orderFinishTime.compareTo(currentDate) <= 0){
            return true;
        }
        return false;
    }

	@Override
	public void placeWonderfulActivity() {
		
	    TbBizPlaceExample tbBizPlaceExample = new TbBizPlaceExample();
        TbBizPlaceExample.Criteria criteria = tbBizPlaceExample.createCriteria();
        criteria.andIsDeleteEqualTo(0).andIsSignEqualTo(PlaceConstants.IS_SIGN_YES).andIsShelvesEqualTo(PlaceConstants.PLACE_SHELVES);
        
        int count = this.tbBizPlaceMapper.countByExample(tbBizPlaceExample);
        int pageSize = 100;
        int index = 0;
        List<TbBizPlace> tbBizPlaceList = null;
        
        //默认每次取100个场馆进行处理
        tbBizPlaceExample.setOrderByClause(" id asc");
        tbBizPlaceExample.setPage(Page.createPage(count, 0, pageSize));
        
        while(!(tbBizPlaceList = tbBizPlaceMapper.selectByExample(tbBizPlaceExample)).isEmpty()) {
        	for (int i = 0; i < tbBizPlaceList.size(); i++) {
        		//更新场馆精彩活动状态
        		updatePlaceWonderfulActivity(tbBizPlaceList.get(i).getId());
        		
        		if (i == tbBizPlaceList.size() - 1) {
        			index = tbBizPlaceList.get(i).getId();
        			criteria.andIdGreaterThan(index);
				}
			}
        }
	}

    @Override
    public void shoppingCartOrderComplete() {
        TbBizPlaceOrderExample tbBizPlaceOrderExample = new TbBizPlaceOrderExample();
        TbBizPlaceOrderExample.Criteria tbBizPlaceOrderCriteria = tbBizPlaceOrderExample.createCriteria();
        tbBizPlaceOrderCriteria.andOrderStatusEqualTo(PlaceConstants.ORDER_PAYED_STATUS);
        tbBizPlaceOrderCriteria.andUseTypeEqualTo(PlaceConstants.ORDER_USE_SHOPPING_CART);
        tbBizPlaceOrderCriteria.andOrderTimeLessThanOrEqualTo(new Date());
        TbBizPlaceOrder tbBizPlaceOrder = new TbBizPlaceOrder();
        tbBizPlaceOrder.setOrderStatus(PlaceConstants.ORDER_COMPLETE_PAY_STATUS);
        tbBizPlaceOrder.setEndTime(new Date());
        tbBizPlaceOrderMapper.updateByExampleSelective(tbBizPlaceOrder, tbBizPlaceOrderExample);
    }


    private void  updatePlaceWonderfulActivity(Integer placeId) {
		int placeActivityStatus = placeWrapper.getPlaceActivityStatus(placeId);
		RedisKey rediskey = new RedisKey(RedisConstants.PLACE_FAMILY_KEY,
				placeId + PlaceConstants.PLACE_VIDEO_CLUB_MASTER_KEY);
		placeRedisTemplate.set(rediskey, String.valueOf(placeActivityStatus));
	}
	
}
